﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using LeadThing.AbpZeroTemplate.SpecialPersons.Authorization;
using LeadThing.AbpZeroTemplate.SpecialPersons.Dtos;
using LeadThing.AbpZeroTemplate.Dto;
using LeadThing.AbpZeroTemplate.Areas;
using LeadThing.AbpZeroTemplate.PersonTypes;
using Abp.Runtime.Session;
using LeadThing.AbpZeroTemplate.Authorization.Roles.Dto;
using LeadThing.AbpZeroTemplate.Authorization.Users;
using LeadThing.AbpZeroTemplate.Authorization.Roles;

namespace LeadThing.AbpZeroTemplate.SpecialPersons
{
    /// <summary>
    /// 重点特殊人群服务实现
    /// </summary>



    public class SpecialPersonAppService : AbpZeroTemplateAppServiceBase, ISpecialPersonAppService
    {
        private readonly IRepository<SpecialPerson, long> _specialPersonRepository;
        private readonly ISpecialPersonListExcelExporter _specialPersonListExcelExporter;
        private readonly IRepository<Area, long> _areaRepository;
        private readonly IRepository<PersonType, long> _personTypeRepository;
        private readonly IRepository<User, long> _userRepository;//用户
        private readonly IRoleAppService _roleService;//角色
        private readonly ISqlExecuter _sqlExecuter;//sql语句接口


        private readonly SpecialPersonManage _specialPersonManage;
        /// <summary>
        /// 构造方法
        /// </summary>
        public SpecialPersonAppService(IRepository<SpecialPerson, long> specialPersonRepository
      , SpecialPersonManage specialPersonManage
      , ISpecialPersonListExcelExporter specialPersonListExcelExporter
      , IRepository<Area, long> areaRepository
      , IRepository<PersonType, long> personTypeRepository
      , IRepository<User, long> userRepository
      , IRoleAppService roleService
      , ISqlExecuter sqlExecuter
  )
        {
            _specialPersonRepository = specialPersonRepository;
            _specialPersonManage = specialPersonManage;
            _specialPersonListExcelExporter = specialPersonListExcelExporter;
            _areaRepository = areaRepository;
            _personTypeRepository = personTypeRepository;
            _userRepository = userRepository;
            _roleService = roleService;
            _sqlExecuter = sqlExecuter;
        }


        #region 实体的自定义扩展方法
        private IQueryable<SpecialPerson> _specialPersonRepositoryAsNoTrack => _specialPersonRepository.GetAll().AsNoTracking();

        /// <summary>
        /// 获取全部特殊人群信息加载到前台地图
        /// </summary>
        /// <returns></returns>
        public PagedResultDto<SpecialPersonLoadPageDto> GetAllSpecialPersonLoadPage(GetSpecialPersonInput input)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@" select TOP {0} *,
                        'SexName' = case Sex when 1 then '男' else '女' end,
                        'PoliticsName' = case Politics when '1' then '党员' when '2' then '团员' else '群众' end,
                        'HealthName' = case Health when '2' then '一般' when '3' then '较差' else '健康' end,
                        'CultureName' = case Culture when '1' then '大专' when '2' then '本科' when '3' then '硕士' when '4' then '博士' when '5' then '中专' when '6' then '高中' when '7' then '初中' else '其他' end,
                        'PersonTypeName' = case PersonTypeID when '1' then '涉军' when '2' then '涉教' when '3' then '原计划生育临时工' when '4' then '刑满释放人员' when '5' then '违法青少年' when '6' then '上访老人' when '7' then '吸毒人员' when '8' then '肇事肇祸精神病人' when '9' then '社区矫正对象' when '10' then '法轮功等邪教人员' when '11' then '低保' else '' end, 
                        'TownTitle' = (select Title from Basic.Area where id = s.TownID),
                        'AreaTitle' = (select Title from Basic.Area where id = s.AreaID),
                        'VillageTitle' = (select Title from Basic.Area where id = s.VillageID),
                         'XPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                          ,'YPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                         from Basic.SpecialPerson s where isDeleted=0 ", input.MaxResultCount);

            var query = _specialPersonRepositoryAsNoTrack;
            string skip = " and Id not in(select top " + input.SkipCount + " Id from Basic.SpecialPerson where isDeleted=0 {0} order by Id desc)";
            string skip1 = "";

            if (!string.IsNullOrWhiteSpace(input.Filter))
            {
                sb.Append(" and Name like '%");
                sb.Append(input.Filter);
                sb.Append("%' ");
                skip1 += string.Format(" and Name like '%{0}%'", input.Filter);
                query = query.Where(u => u.Name.Contains(input.Filter));
            }
            var count = query.Count();
            if (skip1 != "")
            {
                skip = string.Format(skip, skip1);
            }
            else
            {
                skip = skip.Replace("{0}", "");
            }
            sb.Append(skip);
            sb.Append(" order by id desc ");

            var nationList = GetAllSpeNationList();
            var list = _sqlExecuter.SqlQuery<SpecialPersonLoadPageDto>(sb.ToString()).ToList();
            foreach (var item in list)
            {
                var nationModel = nationList.Where(p => p.Value == item.Nation).FirstOrDefault();
                if (nationModel != null)
                {
                    item.NationName = nationModel.DisplayText;
                }
                else
                {
                    item.NationName = "";
                }
            }

            return new PagedResultDto<SpecialPersonLoadPageDto>(count, list); ;
        }

        /// <summary>
        /// 获取所有文化程度
        /// </summary>
        /// <returns></returns>
        public List<ComboboxItemDto> GetAllSpeCultureList()
        {
            return _specialPersonManage.GetAllSpeCultureList();
        }
        /// <summary>
        /// 获取所有民族
        /// </summary>
        /// <returns></returns>
        public List<ComboboxItemDto> GetAllSpeNationList()
        {
            return _specialPersonManage.GetAllSpeNationList();
        }/// <summary>
         /// 获取所有健康状况
         /// </summary>
         /// <returns></returns>
        public List<ComboboxItemDto> GetAllSpeHealthList()
        {
            return _specialPersonManage.GetAllSpeHealthList();
        }/// <summary>
         /// 获取所有政治面貌
         /// </summary>
         /// <returns></returns>
        public List<ComboboxItemDto> GetAllSpePoliticsList()
        {
            return _specialPersonManage.GetAllSpePoliticsList();
        }

        #endregion


        #region 重点特殊人群管理

        /// <summary>
        /// 根据查询条件获取重点特殊人群分页列表
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson)]
        public async Task<PagedResultDto<SpecialPersonListDto>> GetPagedSpecialPersonsAsync(GetSpecialPersonInput input)
        {

            var query = _specialPersonRepositoryAsNoTrack;
            //TODO:根据传入的参数添加过滤条件

            if (!string.IsNullOrWhiteSpace(input.Filter))
            {
                query = query.Where(p => p.Name.Contains(input.Filter));
            }

            #region TODO:根据传入的参数添加过滤条件

            #region 权限验证

            var userID = AbpSession.GetUserId();
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);

            #endregion

            //人员类型ID
            if (input.PersonTypeID != 0)
                query = query.Where(p => p.PersonTypeID == input.PersonTypeID);

            //当事人
            if (!string.IsNullOrWhiteSpace(input.Name))
                query = query.Where(p => p.Name.Contains(input.Name));


            //镇
            if (input.TownID != 0)
                query = query.Where(p => p.TownID == input.TownID);

            //区
            if (input.AreaID != 0)
                query = query.Where(p => p.AreaID == input.AreaID);

            //村庄
            if (input.VillageID != 0)
                query = query.Where(p => p.VillageID == input.VillageID);

            #endregion

            var specialPersonCount = await query.CountAsync();

            var specialPersons = await query
            .OrderByDescending(p => p.Id)
            .PageBy(input)
            .ToListAsync();

            var areaList = _areaRepository.GetAll();
            var personTypeList = _personTypeRepository.GetAll();
            return new PagedResultDto<SpecialPersonListDto>(specialPersonCount,
                specialPersons.Select(item =>
                {
                    var dto = item.MapTo<SpecialPersonListDto>();
                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;

                    var personTypeModel = personTypeList.Where(p => p.Id == dto.PersonTypeID).FirstOrDefault();
                    if (personTypeModel != null)
                        dto.PersonTypeTitle = personTypeModel.Name;
                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 通过Id获取重点特殊人群信息进行编辑或修改 
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson)]
        public async Task<GetSpecialPersonForEditOutput> GetSpecialPersonForEditAsync(NullableIdDto<long> input)
        {
            var output = new GetSpecialPersonForEditOutput();

            SpecialPersonEditDto specialPersonEditDto;

            if (input.Id.HasValue)
            {
                var entity = await _specialPersonRepository.GetAsync(input.Id.Value);
                specialPersonEditDto = entity.MapTo<SpecialPersonEditDto>();
            }
            else
            {
                specialPersonEditDto = new SpecialPersonEditDto();
            }

            output.SpecialPerson = specialPersonEditDto;
            return output;
        }


        /// <summary>
        /// 通过指定id获取重点特殊人群ListDto信息
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson)]
        public async Task<SpecialPersonListDto> GetSpecialPersonByIdAsync(EntityDto<long> input)
        {
            var entity = await _specialPersonRepository.GetAsync(input.Id);

            return entity.MapTo<SpecialPersonListDto>();
        }


        /// <summary>
        /// 新增或更改重点特殊人群
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson)]
        public async Task CreateOrUpdateSpecialPersonAsync(CreateOrUpdateSpecialPersonInput input)
        {
            if (input.SpecialPersonEditDto.Id.HasValue)
            {
                await UpdateSpecialPersonAsync(input.SpecialPersonEditDto);
            }
            else
            {
                await CreateSpecialPersonAsync(input.SpecialPersonEditDto);
            }
        }

        /// <summary>
        /// 新增重点特殊人群
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson_CreateSpecialPerson)]
        public virtual async Task<SpecialPersonEditDto> CreateSpecialPersonAsync(SpecialPersonEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<SpecialPerson>();

            entity = await _specialPersonRepository.InsertAsync(entity);
            return entity.MapTo<SpecialPersonEditDto>();
        }

        /// <summary>
        /// 编辑重点特殊人群
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson_EditSpecialPerson)]
        public virtual async Task UpdateSpecialPersonAsync(SpecialPersonEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新

            var entity = await _specialPersonRepository.GetAsync(input.Id.Value);
            input.MapTo(entity);

            await _specialPersonRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除重点特殊人群
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson_DeleteSpecialPerson)]
        public async Task DeleteSpecialPersonAsync(EntityDto<long> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _specialPersonRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 批量删除重点特殊人群
        /// </summary>
        [AbpAuthorize(SpecialPersonAppPermissions.SpecialPerson_DeleteSpecialPerson)]
        public async Task BatchDeleteSpecialPersonAsync(List<long> input)
        {
            //TODO:批量删除前的逻辑判断，是否允许删除
            await _specialPersonRepository.DeleteAsync(s => input.Contains(s.Id));
        }

        #endregion

        #region 重点特殊人群的Excel导出功能


        public async Task<FileDto> GetSpecialPersonToExcel(EntityDto<long> input)
        {
            var entities = await _specialPersonRepository.GetAll().Where(e => e.PersonTypeID == input.Id).ToListAsync();

            var dtos = entities.MapTo<List<SpecialPersonListDto>>();

            var areas = await _areaRepository.GetAll().ToListAsync();
            var type = await _personTypeRepository.FirstOrDefaultAsync(e => e.Id == input.Id);
            var personType = type == null ? "缺省" : type.Name;

            var nations = GetAllSpeNationList();
            var healths = GetAllSpeHealthList();
            var politics = GetAllSpePoliticsList();
            var cultures = GetAllSpeCultureList();
            foreach (var dto in dtos)
            {
                dto.SexTitle = dto.Sex ? "男" : "女";
                dto.PersonTypeTitle = personType;

                var nation = nations.FirstOrDefault(t => t.Value == dto.Nation);
                dto.Nation = nation == null ? "缺省" : nation.DisplayText;

                var health = healths.FirstOrDefault(t => t.Value == dto.Health);
                dto.Health = health == null ? "缺省" : health.DisplayText;

                var politic = politics.FirstOrDefault(t => t.Value == dto.Politics);
                dto.Politics = politic == null ? "缺省" : politic.DisplayText;

                var culture = cultures.FirstOrDefault(t => t.Value == dto.Culture);
                dto.Culture = culture == null ? "缺省" : culture.DisplayText;


                var town = areas.FirstOrDefault(a => a.Id == dto.TownID);
                dto.TownTitle = town == null ? "缺省" : town.Title;

                var area = areas.FirstOrDefault(a => a.Id == dto.AreaID);
                dto.AreaTitle = area == null ? "缺省" : area.Title;

                var vill = areas.FirstOrDefault(a => a.Id == dto.VillageID);
                dto.VillageTitle = vill == null ? "缺省" : vill.Title;
            }

            var fileDto = _specialPersonListExcelExporter.ExportSpecialPersonToFile(dtos);



            return fileDto;
        }


        #endregion

        #region APP接口

        /// <summary>
        /// 根据查询条件获取重点特殊人群分页列表
        /// </summary>
        public async Task<PagedResultDto<SpecialPersonListDto>> GetPagedSpecialPersonsAPPAsync(GetSpecialPersonAPPInput input)
        {
            var _pageIndex = Convert.ToInt32(input.PageIndex);
            var _pageSize = Convert.ToInt32(input.PageSize);
            var query = _specialPersonRepositoryAsNoTrack;
            //TODO:根据传入的参数添加过滤条件

            #region TODO:根据传入的参数添加过滤条件

            #region 权限验证

            var userID = Convert.ToInt32(input.UserID);
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);

            #endregion

            //人员类型ID
            var personTypeID = Convert.ToInt32(input.PersonTypeID);
            if (personTypeID != 0)
                query = query.Where(p => p.PersonTypeID == personTypeID);

            //当事人
            if (!string.IsNullOrWhiteSpace(input.Name))
                query = query.Where(p => p.Name.Contains(input.Name));

            #endregion

            var specialPersonCount = await query.CountAsync();

            var specialPersons = await query
            .OrderByDescending(p => p.Id)
            .Take(_pageSize * _pageIndex).Skip(_pageSize * (_pageIndex - 1))
            .ToListAsync();

            var areaList = _areaRepository.GetAll();
            var personTypeList = _personTypeRepository.GetAll();
            return new PagedResultDto<SpecialPersonListDto>(specialPersonCount,
                specialPersons.Select(item =>
                {
                    var dto = item.MapTo<SpecialPersonListDto>();
                    var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                    if (townModel != null)
                        dto.TownTitle = townModel.Title;

                    var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                    if (areaModel != null)
                        dto.AreaTitle = areaModel.Title;

                    var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                    if (villModel != null)
                        dto.VillageTitle = villModel.Title;

                    var personTypeModel = personTypeList.Where(p => p.Id == dto.PersonTypeID).FirstOrDefault();
                    if (personTypeModel != null)
                        dto.PersonTypeTitle = personTypeModel.Name;
                    return dto;
                }).ToList());
        }

        /// <summary>
        /// 通过Id获取重点特殊人群信息进行编辑或修改 
        /// </summary>
        public async Task<GetSpecialPersonForEditOutput> GetSpecialPersonForEditAPPAsync(EntityDto<string> input)
        {
            var output = new GetSpecialPersonForEditOutput();

            SpecialPersonEditDto specialPersonEditDto;

            if (!string.IsNullOrWhiteSpace(input.Id))
            {
                var id = Convert.ToInt32(input.Id);
                var entity = await _specialPersonRepository.GetAsync(id);
                specialPersonEditDto = entity.MapTo<SpecialPersonEditDto>();
            }
            else
            {
                specialPersonEditDto = new SpecialPersonEditDto();
            }

            output.SpecialPerson = specialPersonEditDto;
            return output;
        }

        public virtual async Task<SpecialPersonEditDto> CreateSpecialPersonAppAsync(SpecialPersonAPPEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<SpecialPerson>();
            entity = await _specialPersonRepository.InsertAsync(entity);
            return entity.MapTo<SpecialPersonEditDto>();
        }

        /// <summary>
        /// 编辑重点特殊人群
        /// </summary>
        public virtual async Task UpdateSpecialPersonAppAsync(SpecialPersonAPPEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新
            var id = Convert.ToInt32(input.Id);
            var entity = await _specialPersonRepository.GetAsync(id);
            input.MapTo(entity);

            await _specialPersonRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除重点特殊人群
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task DeleteSpecialPersonAppAsync(EntityDto<string> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            var id = Convert.ToInt32(input.Id);
            await _specialPersonRepository.DeleteAsync(id);

        }
        #endregion
    }
}
